package jgespres;

import java.sql.*;
import java.awt.Color;
import java.util.Map;
import java.util.HashMap;
import java.util.logging.*;
import java.util.List;
import java.util.ArrayList;

/**
 * Table des paramètres.
 * 
 * @author guerfyld
 * @version 2.0
 */
public class Tables {
    // Constantes
    private static final String IDENT_DFT = "X";
    private static final Color BCKGRD_DFT = Color.BLACK;
    private static final Color FORGRD_DFT = Color.WHITE;
    
    // Connection à la Base de données
    private Connection conn;
    // Requêtes préparées
    private PreparedStatement selectParameters;
    private PreparedStatement insertParameter;
    private PreparedStatement updateParameter;
    private PreparedStatement deleteParameter;
    private PreparedStatement selectSession;
    private PreparedStatement selectSessionParams;
    private PreparedStatement selectTable;
    
    // Paramètres  à gerer
    private List parameters;
    // Parametres particuliers
    private String[] sessions;
    private Map identList;
    private List statusList;
    private List rowStsList;

    // Logger
    private Logger logger = Logger.getLogger("jgespres");
        
    /**
     * Constructeur
     * 
     * @param connection   Connection à une base JDBC
     */
    public Tables(Connection connection) {
        // Affectation connection
        conn = connection;
        try {
            // Préparation requêtes
            selectParameters = conn.prepareStatement("SELECT idTable, keyTable, text FROM Table2 ORDER BY idTable, keyTable");
            insertParameter = conn.prepareStatement("INSERT INTO Table2 (idTable, keyTable, text) VALUES(?, ?, ?)");
            updateParameter = conn.prepareStatement("UPDATE Table2 SET text = ? WHERE idTable = ? and keyTable = ? ");
            deleteParameter = conn.prepareStatement("DELETE FROM Table2 WHERE idTable = ? and keyTable = ? ");
            selectSession = conn.prepareStatement("SELECT text FROM Table2 WHERE idTable='SESSION' and keyTable = ?");
            selectSessionParams = conn.prepareStatement("SELECT keyTable, text FROM Table2 WHERE idTable = 'IDENT' and right(rtrim(keyTable), 1) = ?");
            selectTable = conn.prepareStatement("SELECT text FROM Table2 WHERE idTable = ? ORDER BY keyTable");
            
            // Chargement initial
            parameters = new ArrayList(50);
            sessions = new String[jgespres.MAXSESSION];
            identList = new HashMap(50);
            statusList = new ArrayList(10);
            rowStsList = new ArrayList(10);
            load();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 
     */
    private boolean load() {
        ResultSet rs;
        
        // Mise à jour table des paramètres
        logger.log(Level.CONFIG, "Mise à jour table des paramétres");
        parameters.clear();
        try {
            rs = selectParameters.executeQuery();
            while (rs.next()) {
                Object[] row= new Object[3];
                row[0] = rs.getString(1).trim();
                row[1] = rs.getString(2).trim();
                row[2] = rs.getString(3).trim();
                parameters.add(row);
                logger.log(Level.FINEST, "Ajout paramètre "+(String)row[0]+"/"+(String)row[1]+"/"+(String)row[2]);
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }
        
        // Mise à jour paramètres des sessions
        logger.log(Level.CONFIG, "Mise à jour paramétres des sessions");
        identList.clear();
        boolean first = true;
        for(int s=jgespres.MAXSESSION-1; s>=0; s--) {
            try {
                selectSession.setString(1, Integer.toString(s));
                rs = selectSession.executeQuery();
                
                // Chargement Libellé de session
                if (rs.next()) {
                    first = false;
                    sessions[s] = rs.getString(1);
                }
                else {
                    sessions[s] = (first) ? null : "Session "+s;
                }
                logger.log(Level.FINEST, "Ajout libellé session ("+first+") "+s+"= "+sessions[s]);
                
                // Chargement Libellé et Style des catégories de thèmes
                if (!first) {
                    selectSessionParams.setString(1, Integer.toString(s));
                    rs = selectSessionParams.executeQuery();
                    while (rs.next()) {
                        // Récupérations élements
                        String ident = rs.getString(1).split(";")[0].trim();
                        String[] elt = rs.getString(2).split(";");
                        // Initialisation
                        String Id = ident + s;
                        Object[] Values = new Object[3];
                        
                        // Mise à jour libellé
                        try {
                            Values[0] = elt[0].trim();
                        }
                        catch (Exception e) {
                            Values[0] = null;
                        }
                        logger.log(Level.FINEST, "Libellé catégorie "+Id+" ="+Values[0]);
                        
                        // Mise à jour couleur fond
                        try {
                            Values[1] = new Color(Integer.parseInt(elt[1].trim(), 16));
                        }
                        catch (Exception e) {
                            Values[1] = null;
                        }
                        logger.log(Level.FINEST, "Couleur fond thème "+Id+" ="+Values[1]);
                        
                        // Mise à jour couleur texte
                        try {
                            Values[2] = new Color(Integer.parseInt(elt[2].trim(), 16));
                        }
                        catch (Exception e) {
                            Values[2] = null;
                        }
                        logger.log(Level.FINEST, "Couleur texte thème "+Id+"= "+Values[2]);
                        
                        // Ajoute données à la liste
                        identList.put(Id, Values);
                    }
                }
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
        
        // Mise à jour paramètres des statuts de cellule
        statusList.clear();
        logger.log(Level.CONFIG, "Mise à jour paramétres Statuts de cellule");
        try {
            // Status par défaut 
            Object[] Values = new Object[2];
            Values[0] = jgespres.getResourceString("Planning.Menu.Status.1");
            Values[1] = null;
            statusList.add(Values);
            // Autres status
            selectTable.setString(1, "CSTATUS");
            rs = selectTable.executeQuery();
            while (rs.next()) {
                String[] elt = rs.getString(1).split(";");
                Values = new Object[3];
                try {
                    Values[0] = elt[0].trim();
                }
                catch (Exception e) {
                    Values[0] = null;
                }
                try {
                    Values[1] = new Color(Integer.parseInt(elt[1].trim(), 16));
                }
                catch (Exception e) {
                    Values[1] = null;
                }
                try {
                    Values[2] = elt[2].trim();
                }
                catch (Exception e) {
                    Values[2] = null;
                }
                statusList.add(Values);
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }

        // Mise à jour paramètres des statuts de ligne
        rowStsList.clear();
        logger.log(Level.CONFIG, "Mise à jour paramétres Statuts de ligne");
        try {
            Object[] Values;
            // Liste status
            selectTable.setString(1, "RSTATUS");
            rs = selectTable.executeQuery();
            while (rs.next()) {
                String[] elt = rs.getString(1).split(";");
                Values = new Object[2];
               try {
                    Values[0] = elt[0].trim();
                }
                catch (Exception e) {
                    Values[0] = null;
                }
                 try {
                    Values[1] = new Color(Integer.parseInt(elt[1].trim(), 16));
                }
                catch (Exception e) {
                    Values[1] = null;
                }
                rowStsList.add(Values);
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }
        
        return true;
    }
    
    /**
     * Récupération liste des sessions
     * 
     * @return          Liste des sessions
     */
    public String[] getSessions() {
        return sessions;
    }
    
    /**
     * Récupération Libellé a afficher d'un poste
     * 
     * @param session       N° session
     * @param ident         Catégorie thème
     * @return              Libellé
     */
    public String getCellLabel(int session, String ident) {
        String Id = ident + session;
        String label;
        
        try {
            label = (String) ((Object[]) identList.get(Id))[0];
        }
        catch (Exception e) {
            label = null;
        }
        
        return (label != null) ? label : IDENT_DFT;
    }
    
    /**
     * Récupération Couleur de fond à afficher d'un poste
     * 
     * @param session       N° session
     * @param ident         Catégorie thème
     * @return              Couleur
     */
    public Color getCellBackground(int session, String ident) {
        String Id = ident + session;
        Color color;
        
        try {
            color = (Color) ((Object[]) identList.get(Id))[1];
        }
        catch (Exception e) {
            color = null;
        }

        return (color != null) ? color : BCKGRD_DFT;
    }

    /**
     * Récupération Couleur du texte à afficher d'un poste
     * 
     * @param session       N° session
     * @param ident         Catégorie thème
     * @return              Couleur
     */
    public Color getCellForeground(int session, String ident) {
        String Id = ident + session;
        Color color;
        
        try {
            color = (Color) ((Object[]) identList.get(Id))[2];
        }
        catch (Exception e) {
            color = null;
        }

        return (color != null) ? color : FORGRD_DFT;
    }

    /**
     * Récupération liste des statuts
     * 
     * @param type      Type status (1=Cell, 2=Row)
     * @return          Nombre de status
     */
    public int getNbStatus(int type) {
        int siz;
        
        switch(type) {
            case 1:
                siz = statusList.size();
                break;

            default:
                siz = rowStsList.size();
                break;
        }
        
        return siz;
    }
    
    /**
     * Récupération liste des statuts
     * 
     * @param type      Type status (1=Cell, 2=Row)
     * @param sts       Status
     * @return          Liste
     */
    public String getStatusLabel(int type, int sts) {
        String label;
        int i = sts -1;
        
        try {
            switch(type) {
                case 1:
                    label = (String) ((Object[]) statusList.get(i))[0];
                    break;

                default:
                    label = (String) ((Object[]) rowStsList.get(i))[0];
                    break;
            }
        }
        catch (Exception e) {
            label = null;
        }
        
        return (label != null) ? label : jgespres.NULL;        
    }

    /**
     * Récupération couleur d'un statut
     * 
     * @param type      Type status (1=Cell, 2=Row)
     * @param sts       Status
     * @return          couleur
     */
    public Color getStatusColor(int type, int sts) {
        Color color;
        int i = sts -1;
        
        try {
            switch(type) {
                case 1:
                    color = (Color) ((Object[]) statusList.get(i))[1];
                    break;

                default:
                    color = (Color) ((Object[]) rowStsList.get(i))[1];
                    break;
            }
        }
        catch (Exception e) {
            color = null;
        }

        return (color != null) ? color : FORGRD_DFT;        
    }
    
    /**
     * Vérifie que Status est expandable
     * 
     * @param sts       Status
     * @return          Oui/Non
     */
    public boolean isStatusExpandable(int sts) {
        boolean ret;
        
        try {
            ret = ((String) ((Object[]) statusList.get(sts-1))[2]).equals("Y");
        }
        catch (Exception e) {
            ret = false;
        }
        return ret;
    }
    
    /**
     * Renvoi valeur paramètre
     * 
     * @param row   Ligne
     * @param col   Colonne (0=Table, 1=Clé, 2=Valeur)
     * @return      Valeur
     */
    public Object getValue(int row, int col) {
        try {
            return ((Object[]) parameters.get(row))[col];
        }
        catch(Exception e) {
            e.printStackTrace();
        }
        
        return null;
    }
    
    /**
     * Renvoi taille de la Table des paramétres
     * 
     * @return      Nbr de lignes
     */
    public final int getSize() {
        return parameters.size();
    }
    
    /**
     * Mise à jour valeur d'un paramétre
     * 
     */
    public void setValue(int row, int col, Object value) {
        String tbl  = (String) getValue(row, 0);
        String key = (String) getValue(row, 1);
        String text = (String) getValue(row, 2);
        switch (col) {
            case 0:
                if (!tbl.equals((String) value)) {
                    delParameter(tbl, key);
                    delParameter((String) value, key);
                    addParameter((String) value, key, text);
                }
                break;
            case 1:
                if (!key.equals((String)value)) {
                    delParameter(tbl, key);
                    delParameter(tbl, (String) value);
                    addParameter(tbl, (String) value, text);
                }
                break;
            case 2:
                if (!text.equals((String) value))
                    updParameter(tbl, key, (String) value);
                break;
        }
    }
    
    /**
     * Ajout d'un paramètre à la table des paramètres
     * 
     * @param table     Nom de la table
     * @param key       Clé de la table
     * @param text      Texte de la table
     */
    public void addParameter(String table, String key, String text) {
        logger.log(Level.FINE, "Ajout table=["+table+"/"+key+"]="+text);
        try {
            insertParameter.setString(1, table);
            insertParameter.setString(2, key);
            insertParameter.setString(3, text);
            insertParameter.executeUpdate();
            load();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Mise à jour d'un paramètre à la table des paramètres
     * 
     * @param table     Nom de la table
     * @param key       Clé de la table
     * @param text      Texte de la table
     */
    public void updParameter(String table, String key, String text) {
        logger.log(Level.FINE, "Mise à jour table=["+table+"/"+key+"]="+text);
        try {
            updateParameter.setString(1, text);
            updateParameter.setString(2, table);
            updateParameter.setString(3, key);
            updateParameter.executeUpdate();
            load();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * Suppression d'un paramètre à la table des paramètres
     *
     * @param table     Nom de la table
     * @param key       Clé de la table
     */
    public void delParameter(String table, String key) {
        logger.log(Level.FINE, "Suppression table=["+table+"/"+key+"]");
        try {
            deleteParameter.setString(1, table);
            deleteParameter.setString(2, key);
            deleteParameter.executeUpdate();
            load();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
